package com.newenergy.wisehome.presenter;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.widget.Toast;

import com.baidu.speech.EventListener;
import com.baidu.speech.EventManager;
import com.baidu.speech.EventManagerFactory;
import com.baidu.speech.asr.SpeechConstant;
import com.newenergy.wisehome.R;
import com.newenergy.wisehome.bd.RecogResult;
import com.newenergy.wisehome.bd.WakeUpResult;
import com.newenergy.wisehome.common.helper.LogHelper;
import com.newenergy.wisehome.config.AppManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by jnl on 2017/10/9.
 */

public class BDPresenter {


    private Context mContext;
    private AppManager mAppManager;
    private Toast mToast;

    public BDPresenter(Context context) {
        mContext = context;
        mAppManager = AppManager.getInstance(context);
    }

    public void initBdSpeech() {
        if (status == STATUS_CHINESE) langure = "cmn-Hans-CN";
        else if (status == STATUS_ENGLISH) langure = "en-GB";
        initWakeUp();
        initRecog();
//        startRecog();
        startWakeUp();
    }

    private static boolean isOfflineEngineLoaded = true;
    private EventManager mAsr;

    protected String samplePath;
    /**
     * 字符串格式的参数
     */
    protected ArrayList<String> stringParams = new
            ArrayList<String>();

    /**
     * int格式的参数
     */
    protected ArrayList<String> intParams = new ArrayList<String>();

    /**
     * bool格式的参数
     */
    protected ArrayList<String> boolParams = new ArrayList<String>();
    private EventManager mWp;

    /**
     * 控制UI按钮的状态
     */

    private static final int STATUS_CHINESE = 1;
    private static final int STATUS_ENGLISH = 2;
    private String langure = "cmn-Hans-CN";//默认语音为中文
    private int status = STATUS_CHINESE;


    /**
     * 在onCreate中调用。初始化离线识别
     */
    protected void initRecog() {
        mAsr = EventManagerFactory.create(mContext, "asr");
        mAsr.registerListener(listener2);
        status = STATUS_CHINESE;

        if (isOfflineEngineLoaded) {
            loadOfflineEngine(fetchOfflineParams());
        }

    }


    private EventListener listener = new EventListener() {
        @Override
        public void onEvent(String name, String params, byte[]
                data, int offset, int length) {

            if (SpeechConstant.CALLBACK_EVENT_WAKEUP_SUCCESS.equals
                    (name)) { //识别唤醒词成功
                WakeUpResult result = WakeUpResult.parseJson(name,
                        params);
                int errorCode = result.getErrorCode();
                if (result.hasError()) { // error不为0依旧有可能是异常情况
//                    Toast.makeText(mContext, " error不为0依旧有可能是异常情况",
//                            Toast.LENGTH_SHORT).show();
                } else {
                    startRecog();
                    String word = result.getWord();
                    /*Toast.makeText(mContext, "结果=-----" + word, Toast
                            .LENGTH_SHORT).show();*/
                    toast("请说出您的命令！");
                }
            } else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_ERROR
                    .equals(name)) { // 识别唤醒词报错
                WakeUpResult result = WakeUpResult.parseJson(name,
                        params);
                int errorCode = result.getErrorCode();
                if (result.hasError()) {
//                    Toast.makeText(mContext, "识别唤醒词报错", Toast
//                            .LENGTH_SHORT).show();
                }
            } else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_STOPED
                    .equals(name)) { //关闭唤醒词
//                Toast.makeText(mContext, "关闭唤醒词", Toast
// .LENGTH_SHORT)
//                        .show();
            } else if (SpeechConstant.CALLBACK_EVENT_WAKEUP_AUDIO
                    .equals(name)) { // 音频回调
//                Toast.makeText(mContext, "音频回调", Toast.LENGTH_SHORT)
//                        .show();
            }

        }
    };


    private EventListener listener2 = new EventListener() {

        private String[] mResults;
        private RecogResult mRecogResult;

        @Override
        public void onEvent(String name, String params, byte[]
                data, int offset, int length) {

            if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_LOADED)) {
//                Toast.makeText(mContext, "ASR正在加载：---" + 1, Toast
//                        .LENGTH_SHORT).show();
            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_UNLOADED)) {
//                Toast.makeText(mContext, "ASR没有加载：---" + 2, Toast
//                        .LENGTH_SHORT).show();
            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_READY)) {
                // 引擎准备就绪，可以开始说话
//                Toast.makeText(mContext, "引擎准备就绪，可以开始说话：---" + 3,
//                        Toast
//                                .LENGTH_SHORT).show();
            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_BEGIN)) {
                // 检测到用户的已经开始说话
//                Toast.makeText(mContext, "检测到用户的已经开始说话：---" + 4,
// Toast
//                        .LENGTH_SHORT).show();

            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_END)) {
                // 检测到用户的已经停止说话
//                Toast.makeText(mContext, "检测到用户的已经停止说话：---" + 5, Toast.LENGTH_SHORT).show();


            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_PARTIAL)) {
                mRecogResult = RecogResult.parseJson(params);
                // 临时识别结果, 长语音模式需要从此消息中取出结果
                mResults = mRecogResult.getResultsRecognition();

            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_FINISH)) {
                if (mRecogResult == null) {
//                    Toast.makeText(mContext, "您输入的指令有误", Toast
//                            .LENGTH_SHORT).show();
                    return;
                }

                if (mRecogResult.hasError()) {
                    /*int errorCode = mRecogResult.getError();
                    Toast.makeText(mContext, "可能的错误：---" + 9, Toast
                            .LENGTH_SHORT).show();*/
                } else {

                    String result = mResults[0];
                    toast(result);
                    notifyRecogResult(result);

//                    startComment(mResults[0]);
//                    Log.e(TAG, mResults[0]);
                }

                mRecogResult = null;

            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_LONG_SPEECH)) { //长语音
//                Toast.makeText(mContext, "长语音：---" + 11, Toast
//                        .LENGTH_SHORT).show();
            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_EXIT)) {
//                Toast.makeText(mContext, "退出语音：---" + 12, Toast
//                        .LENGTH_SHORT).show();
            } else if (name.equals(SpeechConstant
                    .CALLBACK_EVENT_ASR_AUDIO)) {
                if (data.length != length) {

                }
//                Toast.makeText(mContext, "结束说话：---" + 14, Toast
//                        .LENGTH_SHORT).show();
            }

        }
    };

    private void toast(String result) {
        if (mToast == null) {
            mToast = Toast.makeText(mContext, "最终识别结果：" + result,
                    Toast.LENGTH_SHORT);
        }
        mToast.setText(result);
        mToast.show();
    }

    /**
     * 通知识别结果
     *
     * @param result
     */
    private void notifyRecogResult(String result) {
        LogHelper.i("notifyRecogResult:result=" + result);
        toast("RecogResult:" + result);
//        mAppManager.notifySpeechResult(result);
          mAppManager.notifySpeechPinYinResult(result);
    }


    /**
     * 开始录音，点击“开始”按钮后调用。
     */
    protected void startRecog() {
        SharedPreferences sp = PreferenceManager
                .getDefaultSharedPreferences(mContext);
        Map<String, Object> params = fetch(sp);
        params.put(SpeechConstant.LANGUAGE, langure);
        String json = new JSONObject(params).toString();
        mAsr.send(SpeechConstant.ASR_START, json, null, 0, 0);
    }


    /**
     * 开始录音后，手动停止录音。SDK会识别在此过程中的录音。点击“停止”按钮后调用。
     */
    private void stopRecog() {
        mAsr.send(SpeechConstant.ASR_STOP, "{}", null, 0, 0);
    }

    /**
     * 开始录音后，取消这次录音。SDK会取消本次识别，回到原始状态。点击“取消”按钮后调用。
     */
    private void cancelRecog() {
        mAsr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
    }

    public void releaseRecog() {
        cancelRecog();
        if (isOfflineEngineLoaded) {
            mAsr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null,
                    null, 0, 0);
            isOfflineEngineLoaded = false;
        }
        mAsr.unregisterListener(listener);
        mAsr = null;
    }

    /**
     * @param params
     */
    public void loadOfflineEngine(Map<String, Object> params) {
        String json = new JSONObject(params).toString();
        mAsr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, json, null,
                0, 0);
        isOfflineEngineLoaded = true;
        // 没有ASR_KWS_LOAD_ENGINE这个回调表试失败，如缺少第一次联网时下载的正式授权文件。
    }


    public Map<String, Object> fetch(SharedPreferences sp) {

        Map<String, Object> map = new HashMap<String, Object>();
        map.put(SpeechConstant.DECODER, 2);

        parseParamArr(sp, map);

        if (sp.getBoolean("_tips_sound", false)) { // 声音回调
            map.put(SpeechConstant.SOUND_START, R.raw
                    .bdspeech_recognition_start);
            map.put(SpeechConstant.SOUND_END, R.raw
                    .bdspeech_speech_end);
            map.put(SpeechConstant.SOUND_SUCCESS, R.raw
                    .bdspeech_recognition_success);
            map.put(SpeechConstant.SOUND_ERROR, R.raw
                    .bdspeech_recognition_error);
            map.put(SpeechConstant.SOUND_CANCEL, R.raw
                    .bdspeech_recognition_cancel);
        }

        if (sp.getBoolean("_outfile", false)) { // 保存录音文件
            map.put(SpeechConstant.OUT_FILE, samplePath + "/outfile" +
                    ".pcm");
        }

        return map;

    }

    /**
     * 根据 stringParams intParams
     * boolParams中定义的参数名称，提取SharedPreferences相关字段
     *
     * @param sp
     * @param map
     */
    private void parseParamArr(SharedPreferences sp, Map<String,
            Object> map) {
        for (String name : stringParams) {
            if (sp.contains(name)) {
                String tmp = sp.getString(name, "").replaceAll("," +
                        ".*", "").trim();
                if (null != tmp && !"".equals(tmp)) {
                    map.put(name, tmp);
                }
            }
        }
        for (String name : intParams) {
            if (sp.contains(name)) {
                String tmp = sp.getString(name, "").replaceAll("," +
                        ".*", "").trim();
                if (null != tmp && !"".equals(tmp)) {
                    map.put(name, Integer.parseInt(tmp));
                }
            }
        }
        for (String name : boolParams) {
            if (sp.contains(name)) {
                map.put(name, sp.getBoolean(name, false));
            }
        }
    }


    /**********************
     * 离线识别
     *******************************/
    public static Map<String, Object> fetchOfflineParams() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(SpeechConstant.DECODER, 2);
        map.put(SpeechConstant
                        .ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH,
                "asset:///baidu_speech_grammar.bsg");
        map.putAll(fetchSlotDataParam());
        return map;
    }


    public static Map<String, Object> fetchSlotDataParam() {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            JSONObject json = new JSONObject();
            json.put("name", new JSONArray().put("赵六").put("赵六"))
                    .put("appname", new JSONArray().put("手百").put
                            ("度秘"));
            map.put(SpeechConstant.SLOT_DATA, json);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return map;
    }

/**********************离线识别*******************************/


/**********************唤醒词*******************************/

    /**
     * 在onCreate中调用。初始化离线识别
     */
    protected void initWakeUp() {
        mWp = EventManagerFactory.create(mContext, "wp");
        mWp.registerListener(listener);
    }

    /**
     * 开始唤醒，点击“开始”按钮后调用。
     */
    protected void startWakeUp() {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put(SpeechConstant.WP_WORDS_FILE, "assets:///WakeUp" +
                ".bin");
        String json = new JSONObject(params).toString();
        mWp.send(SpeechConstant.WAKEUP_START, json, null, 0, 0);
    }

    /**
     * 停止唤醒，点击“开始”按钮后调用。
     */
    protected void stopWakeUp() {
        mWp.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0);
    }

    /**
     * 开始唤醒，点击“开始”按钮后调用。
     */
    protected void releaseWakeUp() {
        stopWakeUp();
        mWp.unregisterListener(listener);
        mWp = null;
    }


    /**********************
     * 唤醒词
     *******************************/


}
